#include "point2d.h"
#include "utils.h"
#include <QtCore/qmath.h>

Point2d::Point2d(double latitude, double longitude)
{
    this->latitude = latitude;
    this->longitude = longitude;
}

double Point2d::getLatitude() const
{
    return latitude;
}

double Point2d::getRadianLatitude() const
{
    return M_PI * latitude / 180.0;
}

double Point2d::getLongitude() const
{
    return longitude;
}

double Point2d::getRadianLongitude() const
{
    return M_PI * longitude / 180.0;
}

void Point2d::setLatitude(double latitude)
{
    this->latitude = latitude;

}

void Point2d::setLongitude(double longitude)
{
    this->longitude = longitude;
}

const Point2d & Point2d::normalize()
{
    while(qAbs(latitude) > 90.0)
    {
        latitude =  Utils::sign(latitude) * 180.0 - latitude;
        longitude += 180.0;
    }
    while(qAbs(longitude) > 180.0)
        longitude = longitude - Utils::sign(longitude) * 360.0;
    return *this;
}

int Point2d::distance(double lat1, double lon1, double lat2, double lon2)
{
    return (int)(Utils::Radius * 2.0 * qAsin(qSqrt(qPow(qSin(((lat1 - lat2) * M_PI / 360.0)), 2.0) + qCos(lat1 * M_PI / 180.0) * qCos(lat2 * M_PI / 180.0) * qPow(qSin((lon1 - lon2) * M_PI / 360.0), 2.0))));
}

int Point2d::distance(const Point2d & p1, const Point2d & p2)
{
    return distance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude());
}

Point2d & Point2d::operator+=(const Point2d &p)
{
    latitude += p.getLatitude();
    longitude += p.getLongitude();
    return *this;
}

Point2d & Point2d::operator-=(const Point2d &p)
{
    latitude -= p.getLatitude();
    longitude -= p.getLongitude();
    return *this;
}

inline bool operator==(const Point2d & p1, const Point2d & p2)
{
    return p1.getLatitude() == p2.getLatitude() && p1.getLongitude() == p2.getLongitude();
}

inline bool operator!=(const Point2d & p1, const Point2d & p2)
{
    return !(p1 == p2);
}

inline Point2d operator+(const Point2d & p1, const Point2d & p2)
{
    return Point2d(p1.getLatitude() + p2.getLatitude(), p1.getLongitude() + p2.getLongitude());
}

inline Point2d operator-(const Point2d & p1, const Point2d & p2)
{
    return Point2d(p1.getLatitude() - p2.getLatitude(), p1.getLongitude() - p2.getLongitude());
}
inline Point2d operator-(const Point2d & p)
{
    return Point2d(-p.getLatitude(), -p.getLongitude());
}

inline uint qHash(const Point2d & key)
{
    return 360 * ((short)key.getLatitude() + 90) + ((short)key.getLongitude() + 180);
}
